package com.andy.blog.admin.service.impl;

import com.andy.blog.admin.dto.SysConfigDTO;
import com.andy.blog.admin.service.ConfigBusService;
import com.andy.blog.common.constant.CacheConstants;
import com.andy.blog.common.constant.ConfigCenterConstants;
import com.andy.blog.common.core.redis.RedisCache;
import com.andy.blog.common.core.text.Convert;
import com.andy.blog.common.exception.BlogServiceException;
import com.andy.blog.common.page.PageUtilsDTO;
import com.andy.blog.common.utils.TransformUtils;
import com.andy.blog.dal.domain.SysConfigDO;
import com.andy.blog.dal.service.SysConfigDalService;
import com.andy.blog.dal.vo.SysConfigVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * Created by andy on 2023/4/7 11:11
 */
@Service("sysConfigBusService")
public class ConfigBusServiceImpl implements ConfigBusService {

    @Resource
    private SysConfigDalService sysConfigDalService;

    @Resource
    private RedisCache redisCache;


    /**
     * 项目启动时，初始化参数到缓存
     */
    @PostConstruct
    public void init() {
        loadingConfigCache();
    }

    @Override
    public PageUtilsDTO<SysConfigDTO> selectListByPage(SysConfigVO sysConfigVO) {
        IPage<SysConfigDO> page = sysConfigDalService.selectListByPage(sysConfigVO);
        return PageUtilsDTO.build(page.getTotal(), TransformUtils.transformList(page.getRecords(), SysConfigDTO.class));
    }

    @Override
    public List<SysConfigDTO> selectListByCondition(SysConfigVO sysConfigVO) {
        List<SysConfigDO> sysConfigDOS = sysConfigDalService.selectListByCondition(sysConfigVO);
        return TransformUtils.transformList(sysConfigDOS, SysConfigDTO.class);
    }

    @Override
    public SysConfigDTO selectById(Long id) {
        SysConfigDO sysConfigDO = sysConfigDalService.selectById(id);
        return TransformUtils.transform(sysConfigDO, SysConfigDTO.class);
    }

    @Override
    public String selectConfigByKey(String configKey) {
        String configValue = redisCache.getCacheObject(getCacheKey(configKey));

        if (StringUtils.isNotBlank(configValue)) {
            return configValue;
        }

        SysConfigDO sysConfigDO = sysConfigDalService.selectOneConfig(SysConfigVO.builder().configKey(configKey).build());
        if (Objects.nonNull(sysConfigDO)) {
            redisCache.setCacheObject(getCacheKey(configKey), sysConfigDO.getConfigValue());
            return sysConfigDO.getConfigValue();
        }
        return StringUtils.EMPTY;
    }

    @Override
    public void insertConfig(SysConfigVO configVO) {
        if (!sysConfigDalService.checkConfigKeyUnique(configVO)) {
            throw new BlogServiceException("新增参数'" + configVO.getConfigName() + "'失败，参数键名已存在");
        }

        int row = sysConfigDalService.insertConfig(configVO);
        if (row > 0) {
            redisCache.setCacheObject(getCacheKey(configVO.getConfigKey()), configVO.getConfigValue());
        }
    }

    @Override
    public void resetConfigCache() {
        // 清空老数据
        Collection<String> keys = redisCache.keys(CacheConstants.SYS_CONFIG_KEY + "*");
        redisCache.deleteObject(keys);

        // 重新加入缓存
        loadingConfigCache();
    }

    @Override
    public void deleteById(Long configId) {
        SysConfigDO config = sysConfigDalService.selectById(configId);
        sysConfigDalService.deleteById(configId);
        redisCache.deleteObject(getCacheKey(config.getConfigKey()));
    }

    @Override
    public void updateConfig(SysConfigVO configVO) {
        if (!sysConfigDalService.checkConfigKeyUnique(configVO)) {
            throw new BlogServiceException("修改参数'" + configVO.getConfigName() + "'失败，参数键名已存在");
        }

        SysConfigDO temp = sysConfigDalService.selectById(configVO.getId());

        if (!StringUtils.equals(temp.getConfigKey(), configVO.getConfigKey())) {
            redisCache.deleteObject(getCacheKey(temp.getConfigKey()));
        }

        int row = sysConfigDalService.updateConfig(configVO);

        if (row > 0) {
            redisCache.setCacheObject(getCacheKey(configVO.getConfigKey()), configVO.getConfigValue());
        }
    }

    @Override
    public boolean selectCaptchaEnabled() {
        String captchaEnabled = this.selectConfigByKey(ConfigCenterConstants.CAPTCHA_SWITCH);
        if (StringUtils.isBlank(captchaEnabled)) {
            return true;
        }
        return Convert.toBool(captchaEnabled);
    }

    /**
     * 加载参数缓存数据
     */
    public void loadingConfigCache() {
        List<SysConfigDO> configsList = sysConfigDalService.selectListByCondition(null);
        configsList.forEach(config -> redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()));
    }

    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    private String getCacheKey(String configKey) {
        return CacheConstants.SYS_CONFIG_KEY + configKey;
    }
}
